#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/tcp.h> // 用于 TCP_KEEPIDLE, TCP_KEEPINTVL, TCP_KEEPCNT
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <mysql/mysql.h>
#include <errno.h>

#include "../inc/tcp.h"
#include "../inc/login.h"
#include "../inc/agreement.h"

pthread_mutex_t send_mutex = PTHREAD_MUTEX_INITIALIZER;

// -------------------------- 客户端线程处理函数 --------------------------
void *handle_client(void *arg)
{
    client_info_p client = (client_info_p)arg;
    char buf[BUF_SIZE] = {0};
    char resp[BUF_SIZE] = {0};
    int recv_len;

    // 初始化数据库连接
    client->db_conn = db_init();
    if (client->db_conn == NULL)
    {
        send(client->connfd, "[ERROR] 数据库连接失败，无法提供服务", 36, 0);
        goto exit;
    }
    printf("[TCP] 客户端连接: %s:%d\n",
           inet_ntoa(client->client_addr.sin_addr),
           ntohs(client->client_addr.sin_port));

    while (1)
    {
        memset(buf, 0, BUF_SIZE);
        memset(resp, 0, BUF_SIZE);

        // 接收客户端数据（阻塞）
        recv_len = recv(client->connfd, buf, BUF_SIZE - 1, 0);
        if (recv_len < 0)
        {
            // 若错误是“文件描述符无效”（连接已被关闭），直接退出循环
            if (errno == EBADF)
            {
                printf("[TCP] 连接已被关闭（账号在其他设备登录）\n");
                break;
            }
            perror("[TCP] recv error");
            continue;
        }
        else if (recv_len == 0)
        {
            printf("[TCP] 客户端断开连接: %s\n",
                   inet_ntoa(client->client_addr.sin_addr));
            break;
        }

        int res = handle_client_cmd(client, buf, resp);
        if (res == 1)
        {
            break;
        }

        // 发送响应给客户端
        send_message_to_client(client->connfd, resp);
    }

exit:
    // 释放资源
    user_logout(client->db_conn, client->userid);
    mysql_close(client->db_conn);
    close(client->connfd);
    free(client);
    printf("[THREAD] 客户端资源释放完成\n");
    return NULL;
}

int send_message_to_client(int connfd, char *msg)
{
    if (connfd < 0 || msg == NULL || strlen(msg) == 0)
    {
        perror("[ERROR] send_message_to_client: 无效参数");
        return -1;
    }

    pthread_mutex_lock(&send_mutex);
    int send_len = send(connfd, msg, strlen(msg), 0);
    if (send_len < 0)
    {
        perror("[ERROR] send_message_to_client: send失败");
        pthread_mutex_unlock(&send_mutex);
        return -1;
    }
    pthread_mutex_unlock(&send_mutex);

    return send_len;
}

// -------------------------- 服务器初始化 --------------------------
void init_server()
{
    int sockfd, connfd;
    struct sockaddr_in server_addr, client_addr;
    socklen_t client_addr_len = sizeof(client_addr);
    pthread_t tid;

    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        perror("socket error");
        exit(EXIT_FAILURE);
    }

    //  设置端口复用
    int optval = 1;
    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));

    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(PORT);
    server_addr.sin_addr.s_addr = inet_addr(IP);

    if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
    {
        perror("bind error");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    if (listen(sockfd, USERNUM) < 0)
    {
        perror("listen error");
        close(sockfd);
        exit(EXIT_FAILURE);
    }
    printf("服务器启动成功！监听端口: %d\n", PORT);

    while (1)
    {
        connfd = accept(sockfd, (struct sockaddr *)&client_addr, &client_addr_len);
        if (connfd < 0)
        {
            perror("accept error");
            continue;
        }

        // 配置TCP心跳（检测死连接）
        int keepidle = 60, keepintvl = 10, keepcnt = 10;
        setsockopt(connfd, SOL_TCP, TCP_KEEPIDLE, &keepidle, sizeof(keepidle));
        setsockopt(connfd, SOL_TCP, TCP_KEEPINTVL, &keepintvl, sizeof(keepintvl));
        setsockopt(connfd, SOL_TCP, TCP_KEEPCNT, &keepcnt, sizeof(keepcnt));

        // 分配客户端信息结构体
        client_info_p client = (client_info_p)malloc(sizeof(client_info_t));
        if (client == NULL)
        {
            printf("内存分配失败，拒绝连接\n");
            close(connfd);
            continue;
        }
        memset(client, 0, sizeof(client_info_t));
        client->connfd = connfd;
        client->client_addr = client_addr;

        // 创建线程处理客户端请求
        if (pthread_create(&tid, NULL, handle_client, client) != 0)
        {
            perror("pthread create error");
            free(client);
            close(connfd);
            continue;
        }
        pthread_detach(tid); // 线程结束后自动释放资源
    }

    close(sockfd);
}